package com.powernode.service.impl;

import com.powernode.constant.Constants;
import com.powernode.service.LuaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;

/**
 * lua 实现类
 */
@Service
@Slf4j
public class LuaServiceImpl implements LuaService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private DefaultRedisScript<Long> redisScript;

    /**
     * 定义初始化方法
     * 在 spring容器后启动后 立即执行
     */
    @PostConstruct
    public void init() {
        log.info("lua脚本初始化定义");
        redisScript = new DefaultRedisScript<Long>();
        // 设置返回值类型
        redisScript.setResultType(Long.class);
        // 指定lua脚本位置
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("seckill.lua")));
    }


    /**
     * 运行lua脚本 : 原子性判断 限流 + 库存 + 是否已经参与
     *
     * @param id
     * @param userId
     * @return
     */
    @Override
    public Long runLunScript(int id, String userId) {
        log.info("lua脚本启动方法 , 参数如下: {} , {}", id, userId);
        // 定义一个 redis缓存 限流值
        String limitKey = "ip:" + System.currentTimeMillis() / 1000;
        // 定义一个 redis 存储用户秒杀过的对应的商品id
        String holdKey = Constants.REDIS_RESULT + id + userId;
        // 获取商品当前库存key
        String storeKey = Constants.REDIS_STORE + id;
        List<String> keys = Arrays.asList(limitKey, holdKey, storeKey);
        Long execute = stringRedisTemplate.execute(redisScript, keys, userId, String.valueOf(Constants.MAX_LIMIT));
        log.info("lua执行 返回结果如下 : {}", execute);
        // 将执行结果返回
        return execute;
    }
}
